<?php

namespace App\Personal;

// 自定义jwt
class jwt{
    // 签名算法
    private $alg = 'sha256';
    // 令牌的类型
    private $typ = 'JWT';
    // 签发人
    private $iss;
    // 主题
    private $sub = 'token';
    // 受众
    private $aud;
    // 过期时间
    private $exp;
    // 生效时间，在此之前是无效的
    private $nbf;
    // 签发时间
    private $iat;
    // 编号
    private $jti;
    // 过期时间
    private $ttl = 120;
    // 过期刷新时间
    private $refresh_ttl = 240;
    // 头部数据
    private $head;
    // 头部数组
    public $head_arr;
    // 载体
    private $body;
    // 载体数组
    public $body_arr;
    // 签名
    private $sign;
    // token
    public $token;
    // jwt秘钥
    private $jwt_secret;
    // 生成头部
    public function __construct(){
        $this->jwt_secret = getenv('JWT_SECRET');
        $this->ttl = getenv('JWT_TTL') ? getenv('JWT_TTL') : $this->ttl;
        $this->refresh_ttl = getenv('JWT_REFRESH_TTL') ? getenv('JWT_REFRESH_TTL') : $this->refresh_ttl;
    }
    // 设置过期时间
    public function ttl($m){
        $this->ttl = $m;
        return $this;
    }
    // 设置刷新时间
    public function refresh_ttl($m){
        $this->refresh_ttl = $m;
        return $this;
    }
    // 设置主题
    public function sub($m){
        $this->sub = $m;
        return $this;
    }
    // 设置受众
    public function aud($m){
        $this->aud = $m;
        return $this;
    }
    // 生成jwt头
    protected function set_head(){
        $this->head_arr = [
            'alg' => $this->alg,
            'typ' => $this->typ,
        ];
        $this->head = $this->base64url_encode(json_encode($this->head_arr));
    }
    // 生成jwt载荷
    protected function set_body(){
        $this->iat = time();
        $this->body_arr = [
            'sub' => $this->sub,
            'aud' => $this->aud,
            'iat' => $this->iat,
            'exp' => $this->iat + $this->ttl * 60,
        ];
        $this->body = $this->base64url_encode(json_encode($this->body_arr));
    }
    // 设置签名
    protected function set_sign(){
        $this->set_head();
        $this->set_body();
        $this->sign = $this->base64url_encode(hash_hmac('sha256', $this->head . '.' . $this->body, $this->jwt_secret));
    }
    public function check_sign(){
        $sign = $this->base64url_encode(hash_hmac('sha256', $this->head . '.' . $this->body, $this->jwt_secret));
        if($sign != $this->sign) return [404, 'token签名错误'];
    }
    // 设置token
    protected function set_token(){
        $this->set_sign();
        $this->token = $this->head . '.' . $this->body . '.' . $this->sign;
    }
    // 重置token
    protected function reset_token(){
        $this->set_token();
        return $this->token;
    }
    // 生成jwt
    public function get_token(){
        if($this->token){
            return $this->token;
        }
        return $this->reset_token();
    }
    // 添加需要解析的token
    public function add_token($token){
        $this->token = $token;
        return $this;
    }
    // 解析token
    public function parse_toekn($request){
        $token = $request->token ?? '';
        $token = $token ? $token : $this->token;
        if(!$token){
            // 从header中获取
            $app_token = $request->header('Authorization', '');
            if(empty($app_token)){
                return [-1,"token不存在"];
            }
            $token = explode(' ', $app_token)[1];
        }
        $this->token = $token;
        $arr = explode('.', $token);
        $this->head = $arr[0];
        $this->head_arr = json_decode(base64_decode($arr[0]));
        $this->body = $arr[1];
        $this->body_arr = json_decode(base64_decode($arr[1]));
        $this->exp = $this->body_arr->exp;
        $this->sign = $arr[2];
//        $this->check_sign();
        return $this;
    }
    // 验证token有效期
    public function check(){
        // 验证token有效期
        if($this->exp < time()){
            return [403, 'token过期'];
        }
        return $this;
    }
    // 刷新token
    public function refresh_token(){
        $this->can_refresh();
        $this->sub = $this->body_arr->sub;
        $this->aud = $this->body_arr->aud;
        return $this->reset_token();
    }
    // 是否能刷新token
    private function can_refresh(){
        if(!$this->token){
            return [404, 'token不存在'];
        }
        // 验证token能否刷新
        if($this->exp < (time() - $this->refresh_ttl * 60)){
            return [404, 'token刷新期已过'];
        }
    }
    // 生成base64
    protected function base64url_encode($data) {
        return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
    }
}

